package com.guguskins.back.utils.steam;

import com.guguskins.back.common.exception.GlobalException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class SteamLoginUtil {


    public static void main(String[] args) throws UnsupportedEncodingException {
        String url = getUrl("http://guguskinn.cn.utools.club/inner/steamCallback");
        System.out.println(url);
    }

    final static String STEAM_LOGIN = "https://steamcommunity.com/openid/login";

    /**
     * 组装steam登录url
     */
    public static String getUrl(String returnTo) {

        Map<String, String> params = new HashMap<>();
        // String loginTicket = request.getAttribute("loginTicket")==null ? "" :
        // "?lt="+ request.getAttribute("loginTicket").toString();
        // params.put("lt", request.getAttribute("loginTicket")==null
        // ?"":request.getAttribute("loginTicket").toString());
        params.put("openid.ns", "http://specs.openid.net/auth/2.0");
        params.put("openid.mode", "checkid_setup");
        params.put("openid.return_to", returnTo);
        params.put("openid.realm", returnTo);
        params.put("openid.identity", "http://specs.openid.net/auth/2.0/identifier_select");
        params.put("openid.claimed_id", "http://specs.openid.net/auth/2.0/identifier_select");
        return STEAM_LOGIN + "?" + SteamLoginUtil.getUrlParamsByMap(params);
    }

    /**
     * 将数据提交steam进行验证，是否成功登录
     *
     * @param request
     * @return boolean
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String validate(Map<String, String> request) {
        RequestConfig defaultRequestConfig = RequestConfig.custom()
//                .setSocketTimeout(5000)
//                .setConnectTimeout(5000)
//                .setConnectionRequestTimeout(5000)
                .build();
        CloseableHttpClient httpclient = null;
        HttpPost httppost = null;
        try {
            Object signed = request.get("openid.signed");
            if (signed == null || "".equals(signed)) {
                return "";
            }
            httpclient = HttpClients.createDefault();
            httppost = new HttpPost(STEAM_LOGIN + "?" + SteamLoginUtil.getUrlParamsByMap(request));
            httppost.setConfig(defaultRequestConfig);
            List<NameValuePair> nvps = new ArrayList<>();

            String[] signeds = signed.toString().split(",");
            for (String s : signeds) {
                String val = request.get("openid." + s);
                nvps.add(new BasicNameValuePair("openid." + s, val == null ? "" : val));
            }
            nvps.add(new BasicNameValuePair("openid.mode", "check_authentication"));
            httppost.setEntity(new UrlEncodedFormEntity(nvps));
            System.err.println(STEAM_LOGIN + "?" + SteamLoginUtil.getUrlParamsByMap(request));
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if (entity == null) {
                return "";
            }
            InputStream instreams = entity.getContent();
            String result = SteamLoginUtil.convertStreamToString(instreams);
            // Do not need the rest
            httppost.abort();
            String steamid = "";
            steamid = request.get("openid.claimed_id");
            steamid = steamid.replace("https://steamcommunity.com/openid/id/", "");
            if (!result.contains("is_valid:true")) {
                return "";
            }
            return steamid;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httppost != null) {
                httppost.releaseConnection();
            }
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

    public static String getSteamId(Map<String, String> request) {
        return request.get("openid.claimed_id").replace("https://steamcommunity.com/openid/id/", "");
    }

    /**
     * 将url中传递参数转化为map 其中值进行encode
     *
     * @param param aa=11&bb=22&cc=33
     * @return
     * @throws UnsupportedEncodingException
     */
    public static Map<String, String> getUrlParams(String param) throws UnsupportedEncodingException {
        Map<String, String> map = new HashMap<>(0);
        if (isEmpty(param)) {
            return map;
        }
        String[] params = param.split("&");
        for (String s : params) {
            String[] p = s.split("=");
            if (p.length == 2) {
                map.put(p[0], URLDecoder.decode(p[1], "UTF-8"));
            }
        }
        return map;
    }

    /**
     * 将map转化为url可携带的参数字符串
     */
    public static String getUrlParamsByMap(Map<String, String> map) {
        if (map == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            // 解码
            try {
                sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                log.error("编码错误", e);
                throw new GlobalException();
            }
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = substringBeforeLast(s);
        }
        return s;
    }

    public static String convertStreamToString(InputStream is) {

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    private static String substringBeforeLast(String str) {
        if (isEmpty(str) || isEmpty("&")) {
            return str;
        }
        int pos = str.lastIndexOf("&");
        if (pos == -1) {
            return str;
        }
        return str.substring(0, pos);
    }
    // Empty checks
    //-----------------------------------------------------------------------

    /**
     * <p>Checks if a String is empty ("") or null.</p>
     *
     * <pre>
     * StringUtils.isEmpty(null)      = true
     * StringUtils.isEmpty("")        = true
     * StringUtils.isEmpty(" ")       = false
     * StringUtils.isEmpty("bob")     = false
     * StringUtils.isEmpty("  bob  ") = false
     * </pre>
     *
     * <p>NOTE: This method changed in Lang version 2.0.
     * It no longer trims the String.
     * That functionality is available in isBlank().</p>
     *
     * @param str the String to check, may be null
     * @return <code>true</code> if the String is empty or null
     */
    private static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }
}
